package com.demo.springboot底层演示.启动流程;

import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.DefaultApplicationArguments;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.annotation.AnnotatedBeanDefinitionReader;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.io.ClassPathResource;

public class Test {
	
	public static void main(String[] args) throws Exception {
		SpringApplication app = new SpringApplication(Test.class);
		app.addInitializers(contxt -> System.out.println("执行初始化器增强..."));
		System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>> 2. 封装启动args");
		DefaultApplicationArguments arguments = new DefaultApplicationArguments(args);
		
		System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>> 8. 创建容器");
		GenericApplicationContext context = new GenericApplicationContext();
		
		System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>> 9. 准备容器");
		for(ApplicationContextInitializer initializer : app.getInitializers()) {
			initializer.initialize(context);
		}
		
		System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>> 10. 加载bean定义");
		DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory();
		AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(beanFactory);
		// 解析@Configuration里的bean
		reader.register(Config.class);
		// 从xml里解析
		XmlBeanDefinitionReader reader2 = new XmlBeanDefinitionReader(beanFactory);
		reader2.loadBeanDefinitions(new ClassPathResource("b03.xml"));
		ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(beanFactory);
		scanner.scan("com.demo.springboot底层演示.启动流程");
		
		System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>> 11. refresh容器");
		context.refresh();
		
		for(String name : context.getBeanDefinitionNames()) {
			System.out.println("name: " + name + " 来源：" + context.getBeanFactory().getBeanDefinition(name).getResourceDescription());
		}
		
		System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>> 12. 执行runner");
		for(CommandLineRunner runner : context.getBeansOfType(CommandLineRunner.class).values()) {
			runner.run(args);
		}
		for(ApplicationRunner runner : context.getBeansOfType(ApplicationRunner.class).values()) {
			runner.run(arguments);
		}
	}
	
	@Configuration
	static class Config {
		@Bean
		public Bean5 bean5() {
			return new Bean5();
		}
		
		@Bean
		public CommandLineRunner commandLineRunner() {
			return new CommandLineRunner() {
				@Override
				public void run(String... args) throws Exception {
					System.out.println("commandLineRunner()...");
				}
			};
		}
		
		@Bean
		public ApplicationRunner applicationRunner() {
			return new ApplicationRunner() {
				@Override
				// ApplicationArguments: 参数对象是第二步创建的
				public void run(ApplicationArguments args) throws Exception {
					System.out.println("applicationRunner()...");
				}
			};
		}
		
	}

}
